package com.mzj.saas.mservice.property.service;

import com.mzj.saas.commons.Constant;
import com.mzj.saas.commons.KeyWorker;
import com.mzj.saas.commons.ResultBean;
import com.mzj.saas.commons.enums.BacklogItemTypeEnum;
import com.mzj.saas.commons.enums.PaymentTypeEnum;
import com.mzj.saas.commons.util.DataUtils;
import com.mzj.saas.commons.vo.redis.TokenRedisVo;
import com.mzj.saas.config.pay.PayConfig;
import com.mzj.saas.mservice.backlog.entity.BacklogItem;
import com.mzj.saas.mservice.backlog.repository.BacklogItemRepository;
import com.mzj.saas.mservice.community.entity.Community;
import com.mzj.saas.mservice.community.entity.CommunityBuild;
import com.mzj.saas.mservice.community.entity.CommunityBuildUnit;
import com.mzj.saas.mservice.community.repository.CommunityBuildRepository;
import com.mzj.saas.mservice.community.repository.CommunityBuildUnitRepository;
import com.mzj.saas.mservice.community.repository.CommunityRepository;
import com.mzj.saas.mservice.eligible.entity.DepartmentHierarchy;
import com.mzj.saas.mservice.eligible.service.DepartmentHierarchyService;
import com.mzj.saas.mservice.house.entity.House;
import com.mzj.saas.mservice.house.repository.HouseRepository;
import com.mzj.saas.mservice.property.common.RepairsStatusEnum;
import com.mzj.saas.mservice.property.entity.EstateRepairsCostDetail;
import com.mzj.saas.mservice.property.entity.EstateRepairsRecord;
import com.mzj.saas.mservice.property.entity.RepairsPaymentOrder;
import com.mzj.saas.mservice.property.repository.EstateRepairsCostDetailRepository;
import com.mzj.saas.mservice.property.repository.EstateRepairsRecordRepository;
import com.mzj.saas.mservice.property.repository.RepairsPaymentOrderRepository;
import com.mzj.saas.mservice.property.vo.RepairsPaymentRedisVo;
import com.mzj.saas.mservice.property.vo.RepairsPaymentVo;
import com.mzj.saas.mservice.sys.entity.AppUser;
import com.mzj.saas.mservice.sys.entity.WechatAccount;
import com.mzj.saas.mservice.sys.repository.AppUserRepository;
import com.mzj.saas.mservice.sys.repository.WechatAccountRepository;
import com.mzj.saas.redis.RedisService;
import com.mzj.saas.sdk.pay.alipay.AliPayRequest;
import com.mzj.saas.sdk.pay.vo.AliPay;
import com.mzj.saas.sdk.pay.vo.WxPay;
import com.mzj.saas.sdk.pay.wxpay.WxPayRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Service
public class RepairsAppService {
    private static final Logger log = LoggerFactory.getLogger(RepairsAppService.class);

    @Autowired
    private RedisService redisService;
    @Autowired
    private PayConfig payConfig;
    @Autowired
    private EstateRepairsRecordRepository estateRepairsRecordRepository;
    @Autowired
    private EstateRepairsCostDetailRepository estateRepairsCostDetailRepository;
    @Autowired
    private HouseRepository houseRepository;
    @Autowired
    private WechatAccountRepository wechatAccountRepository;
    @Autowired
    private DepartmentHierarchyService departmentHierarchyService;
    @Autowired
    private RepairsPaymentOrderRepository repairsPaymentOrderRepository;
    @Autowired
    private AppUserRepository appUserRepository;
    @Autowired
    private CommunityRepository communityRepository;
    @Autowired
    private CommunityBuildRepository communityBuildRepository;
    @Autowired
    private CommunityBuildUnitRepository communityBuildUnitRepository;
    @Autowired
    private BacklogItemRepository backlogItemRepository;

    @Value("${officialAccount.appId}")
    private String officialAccountAppId;

    public ResultBean<Map<String, Object>> payment(String accessToken, RepairsPaymentVo vo) {
        try {
            log.info("RepairsAppService 维修支付 payment vo={}", vo.toString());

            if (vo.getRepairsId() == null || vo.getPaymentType() == null) {
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();
            // 操作用户企业id
            Long enterpriseId = tokenRedisVo.getEnterpriseId();

            Optional<EstateRepairsRecord> recordOpt = estateRepairsRecordRepository.findById(vo.getRepairsId());
            if (!recordOpt.isPresent()) {
                log.error("RepairsAppService payment 未找到维修记录 repairsId={}", vo.getRepairsId());
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }
            EstateRepairsRecord record = recordOpt.get();

            if (record.getStatus() == RepairsStatusEnum.COMPLETED.getStatus()) {
                log.warn("RepairsAppService payment 维修费用已支付,无需重复支付 repairsId={}", vo.getRepairsId());
                return ResultBean.failedResultWithMsg("当前维修费已支付,无需重复支付");
            }

            Optional<House> houseOpt = houseRepository.findById(record.getHouseId());
            if (!houseOpt.isPresent()) {
                log.error("RepairsAppService payment 未找到房屋 houseId={}", record.getHouseId());
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            List<EstateRepairsCostDetail> costDetailList = estateRepairsCostDetailRepository.findByRepairsId(vo.getRepairsId());
            if (CollectionUtils.isEmpty(costDetailList)) {
                log.error("RepairsAppService payment 未找到报修收费项目明细  repairsId={}", vo.getRepairsId());
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            Integer totalCost = costDetailList.stream().mapToInt(EstateRepairsCostDetail::getTotalCost).sum();
            BigDecimal totalCoseAmount = DataUtils.IntegerToBigdecimal(totalCost);

            House house = houseOpt.get();
            Integer houseNature = house.getHouseNature();//性质:1公租房、2商品房、3经济适用房、5其它
            Long orgId = house.getOrgId();//产权单位id
            Long housePropertyId = house.getHousePropertyId();//物业id

            RepairsPaymentRedisVo redisVo = new RepairsPaymentRedisVo();
            String outTradeNo = String.valueOf(KeyWorker.nextId());
            redisVo.setOutTradeNo(outTradeNo);
            redisVo.setOrgId(housePropertyId);
            redisVo.setRepairsId(vo.getRepairsId());
            redisVo.setPaymentStatus(0);
            redisVo.setUserId(userId);
            redisVo.setTotalAmount(totalCoseAmount);
            redisVo.setBusinessType(2);
            String title = "房屋管家-报修费用";

            //企业信息
            DepartmentHierarchy departmentHierarchy = departmentHierarchyService.getEnterpriseInfo(housePropertyId);
            if (departmentHierarchy == null) {
                log.warn("RepairsAppService payment 未找到机构/企业 houseNature={}, orgId={}, housePropertyId={}", houseNature, orgId, housePropertyId);
                return ResultBean.failedResultWithMsg("企业信息错误");
            }

            //0元支付
            if (DataUtils.doubleToInteger(totalCoseAmount.doubleValue()) == 0) {
                return zeroPayment(redisVo);
            }

            if (vo.getPaymentType() == PaymentTypeEnum.WECHAT.getValue()) {
                WechatAccount account = null;
                // 根据企业设置, 获取收款方式(平台收款, 企业商户号收款)
                // 收款方式：0平台商户号收款 1企业商户号收款
                if (departmentHierarchy.getMerchantsType() == 0) {
                    // 0为平台收款商户号企业id
                    account = wechatAccountRepository.findByOrgIdAndType(0L, PaymentTypeEnum.WECHAT.getValue());
                } else {
                    // 默认使用企业账户号收款
                    account = wechatAccountRepository.findByOrgIdAndType(housePropertyId, PaymentTypeEnum.WECHAT.getValue());
                }

                if (account == null) {
                    log.warn("RepairsAppService payment 未找到微信商户配置,请联系负责人orgId={}", orgId);
                    return ResultBean.failedResultWithMsg("未找到微信商户配置,请联系客服");
                }

                String appId = redisService.getValue(Constant.WX_APPID);
                String attac = outTradeNo;
                String spbillCreateIp = redisService.getValue(Constant.SPBILL_CREATE_IP);
                WxPay wxpay = new WxPay(appId, account.getMchId(), outTradeNo, attac, totalCost, title,
                        account.getMchApiKey(), null, payConfig.getWxNotifyUrl(), payConfig.getUnifiedApi(),
                        spbillCreateIp);
                Map<String, Object> result = new WxPayRequest(wxpay).unifiedByApp();
                if (result == null) {
                    return ResultBean.failedResultWithMsg("微信支付异常,请联系客服");
                }
                redisVo.setMchApiKey(account.getMchApiKey());
                redisVo.setMerchantId(account.getId());
                redisService.putPaymentRepairs(redisVo);
                return ResultBean.successfulResult(result);
            }

            if (vo.getPaymentType() == PaymentTypeEnum.ALI.getValue()) {
                WechatAccount account = null;
                // 收款方式：0平台商户号收款 1企业商户号收款
                if (departmentHierarchy.getMerchantsType() == 0) {
                    // 0为平台收款商户号企业id
                    account = wechatAccountRepository.findByOrgIdAndType(0L, PaymentTypeEnum.ALI.getValue());
                } else {
                    // 默认使用企业账户号收款
                    account = wechatAccountRepository.findByOrgIdAndType(housePropertyId, PaymentTypeEnum.ALI.getValue());
                }

                if (account == null) {
                    log.warn("RepairsAppService payment 未找到支付宝配置,请联系负责人 orgId={}", orgId);
                    return ResultBean.failedResultWithMsg("未找到支付宝配置,请联系负责人");
                }
                String passbackParams = outTradeNo;

                AliPay alipay = new AliPay(account.getMchId(), account.getPrivateKey(), account.getPublicKey(),
                        outTradeNo, totalCoseAmount.toString(), title, "QUICK_MSECURITY_PAY", passbackParams,
                        payConfig.getAliNotifyUrl());

                Map<String, Object> result = new AliPayRequest(alipay).appPay();

                if (result == null) {
                    return ResultBean.failedResultWithMsg("支付宝支付异常,请联系客服");
                }
                redisVo.setPublicKey(account.getPublicKey());
                redisVo.setMerchantId(account.getId());
                redisService.putPaymentRepairs(redisVo);
                return ResultBean.successfulResult(result);
            }
            return ResultBean.successfulResult(null);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    public ResultBean<Map<String, Object>> appletPayment(String accessToken, RepairsPaymentVo vo) {
        try {
            log.info("RepairsAppService 维修支付 appletPayment vo={}", vo.toString());

            if (vo.getRepairsId() == null) {
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            TokenRedisVo tokenRedisVo = redisService.findTokenVo(accessToken);
            if (tokenRedisVo == null) {
                return ResultBean.failedResultOfToken();
            }
            String userId = tokenRedisVo.getId();
            // 操作用户企业id
            String openId = null;
            Optional<AppUser> id = appUserRepository.findById(userId);
            Long enterpriseId = tokenRedisVo.getEnterpriseId();

            if (!id.isPresent()){
                log.error("RepairsAppService appletPayment 未找到用户 userId={}", userId);
                return ResultBean.failedResultOfParamWithMsg("用户不存在");
            }
            Optional<EstateRepairsRecord> recordOpt = estateRepairsRecordRepository.findById(vo.getRepairsId());
            if (!recordOpt.isPresent()) {
                log.error("RepairsAppService appletPayment 未找到维修记录 repairsId={}", vo.getRepairsId());
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }
            EstateRepairsRecord record = recordOpt.get();

            if (record.getStatus() == RepairsStatusEnum.COMPLETED.getStatus()) {
                log.warn("RepairsAppService appletPayment 维修费用已支付,无需重复支付 repairsId={}", vo.getRepairsId());
                return ResultBean.failedResultWithMsg("当前维修费已支付,无需重复支付");
            }

            Optional<House> houseOpt = houseRepository.findById(record.getHouseId());
            if (!houseOpt.isPresent()) {
                log.error("RepairsAppService appletPayment 未找到房屋 houseId={}", record.getHouseId());
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            List<EstateRepairsCostDetail> costDetailList = estateRepairsCostDetailRepository.findByRepairsId(vo.getRepairsId());
            if (CollectionUtils.isEmpty(costDetailList)) {
                log.error("RepairsAppService appletPayment 未找到报修收费项目明细  repairsId={}", vo.getRepairsId());
                return ResultBean.failedResultOfParamWithMsg("参数错误");
            }

            openId = id.get().getOpenId();
            Integer totalCost = costDetailList.stream().mapToInt(EstateRepairsCostDetail::getTotalCost).sum();
            BigDecimal totalCoseAmount = DataUtils.IntegerToBigdecimal(totalCost);

            House house = houseOpt.get();
            Integer houseNature = house.getHouseNature();//性质:1公租房、2商品房、3经济适用房、5其它
            Long orgId = house.getOrgId();//产权单位id
            Long housePropertyId = house.getHousePropertyId();//物业id

            RepairsPaymentRedisVo redisVo = new RepairsPaymentRedisVo();
            String outTradeNo = String.valueOf(KeyWorker.nextId());
            redisVo.setOutTradeNo(outTradeNo);
            redisVo.setOrgId(housePropertyId);
            redisVo.setRepairsId(vo.getRepairsId());
            redisVo.setPaymentStatus(0);
            redisVo.setUserId(userId);
            redisVo.setTotalAmount(totalCoseAmount);
            redisVo.setBusinessType(2);
            String title = "房屋管家-报修费用";

            //企业信息
            DepartmentHierarchy departmentHierarchy = departmentHierarchyService.getEnterpriseInfo(housePropertyId);
            if (departmentHierarchy == null) {
                log.warn("RepairsAppService appletPayment 未找到机构/企业 houseNature={}, orgId={}, housePropertyId={}", houseNature, orgId, housePropertyId);
                return ResultBean.failedResultWithMsg("企业信息错误");
            }

            //0元支付
            if (DataUtils.doubleToInteger(totalCoseAmount.doubleValue()) == 0) {
                return zeroPayment(redisVo);
            }

            // 根据企业设置, 获取收款方式(平台收款, 企业商户号收款)
            // 收款方式：0平台商户号收款 1企业商户号收款
            WechatAccount account = wechatAccountRepository.findByOrgIdAndType(housePropertyId, PaymentTypeEnum.WECHAT.getValue());
            // 默认使用企业账户号收
            if (account == null) {
                log.warn("RepairsAppService appletPayment 未找到微信商户配置,请联系负责人orgId={}", orgId);
                return ResultBean.failedResultWithMsg("未找到微信商户配置,请联系客服");
            }

            String appId = "";
            if(tokenRedisVo.getFlag() == 2){
                appId =  redisService.getValue(Constant.WX_APPLET_APPID);
            }else if (tokenRedisVo.getFlag() == 3){
                appId =  redisService.getValue(Constant.WX_APARTMENT_APPID);
            }else if (tokenRedisVo.getFlag() == 5){
                appId = officialAccountAppId;
            }
            String attac = outTradeNo;
            String spbillCreateIp = redisService.getValue(Constant.SPBILL_CREATE_IP);
            WxPay wxpay = new WxPay(appId, account.getMchId(), outTradeNo, attac, totalCost, title,
                    account.getMchApiKey(), openId, payConfig.getWxNotifyUrl(), payConfig.getUnifiedApi(),
                    spbillCreateIp);
            Map<String, Object> result = new WxPayRequest(wxpay).unifiedByMini();
            if (result == null) {
                return ResultBean.failedResultWithMsg("微信支付异常,请联系客服");
            }
            redisVo.setMchApiKey(account.getMchApiKey());
            redisVo.setMerchantId(account.getId());
            redisService.putPaymentRepairs(redisVo);
            return ResultBean.successfulResult(result);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }

    public ResultBean<Map<String, Object>> zeroPayment(RepairsPaymentRedisVo redisVo) {
        try {
            ResultBean<Map<String, Object>> resultBean = new ResultBean<>();
            resultBean.setCode("10009");
            resultBean.setMsg("0元支付成功");

            Optional<EstateRepairsRecord> recordOpt = estateRepairsRecordRepository.findById(redisVo.getRepairsId());
            EstateRepairsRecord record = recordOpt.get();
            record.setStatus(RepairsStatusEnum.COMPLETED.getStatus());
            estateRepairsRecordRepository.save(record);

            // 更新支付记录
            Date payTime = new Date();
            RepairsPaymentOrder payment = new RepairsPaymentOrder();
            payment.setRepairsId(record.getId());
            payment.setOrderNumber(redisVo.getOutTradeNo());
            payment.setPayResult(1);
            payment.setPayUserId(redisVo.getUserId());
            payment.setTotalAmount(0);
            payment.setPayTime(payTime);
            payment.setPayType(1);
            repairsPaymentOrderRepository.save(payment);


            // 新增消息推送
            BacklogItem backlogItem = new BacklogItem();
            backlogItem.setHouseId(record.getHouseId());
            // 如果是公租房取产权单位id，如果是非公租房取物业公司id
            backlogItem.setType(BacklogItemTypeEnum.COMPLAIN_SUGGEST_FIX.getValue());
            backlogItem.setTitle("报事报修已完成");
            List<House> houseList = houseRepository.findByIdAndStatus(record.getHouseId(), 1);
            House house = houseList.get(0);
            Optional<Community> community = communityRepository.findById(house.getResidenceCommunityId());
            Optional<CommunityBuild> communityBuild = communityBuildRepository.findById(house.getBuildingNum());
            Optional<CommunityBuildUnit> communityBuildUnit = communityBuildUnitRepository.findById(house.getUnit());
            backlogItem.setContent(community.get().getName() + communityBuild.get().getName() + "栋" + communityBuildUnit.get().getName() + "单元" + house.getRoomNumber() + "号，报事报修已维修完成！" );
            backlogItem.setBusinessStatus("待查看");
            backlogItem.setHandleStatus(0);// 0未读/未处理
            backlogItem.setOperatorId(record.getOperatorId());
            backlogItem.setCreateTime(new Date());
            backlogItem.setMatchUserId(record.getAppUserId());
            backlogItemRepository.save(backlogItem);

            return resultBean;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return ResultBean.failedResultOfException();
        }
    }


}
